using System;

namespace Admin.NET.Application.DL645;

/// <summary>
/// 电力645协议
/// </summary>
public class DL645Agreement
{
	private string _passwd = "33333333";

	private string _operatorcode = "33333333";

	/// <summary>
	/// 数据解析
	/// </summary>
	/// <param name="infos"></param>
	public static AgreementAnalysis DL645Analysis(Span<byte> infos)
	{
		AgreementAnalysis analysis = new AgreementAnalysis();
		Span<byte> data;
		if (infos[0] == 254)
		{
			int codeIndexInfos = 1;
			data = infos.Slice(1);
			for (; infos[codeIndexInfos] == 254; codeIndexInfos++)
			{
				data = data.Slice(1);
			}
		}
		else
		{
			data = infos;
		}
		if (data.Length < 9)
		{
			new ArgumentException("当前解析参数有误");
		}
		string address = "";
		Span<byte> addressbyte = data.Slice(1, 6);
		Span<byte> span = addressbyte;
		for (int i = 0; i < span.Length; i++)
		{
			byte item = span[i];
			address += item.ToString("x2");
		}
		analysis.Address = address;
		string type = data[8].ToString("x2").ToUpper();
		if (1 == 0)
		{
		}
		bool flag = type switch
		{
			"91" => AnalysisRead(analysis, data, AgreementaType.Reading, sucess: true), 
			"D1" => AnalysisRead(analysis, data, AgreementaType.Reading, sucess: false), 
			"92" => AnalysisRead(analysis, data, AgreementaType.Reading, sucess: true), 
			"B2" => AnalysisRead(analysis, data, AgreementaType.ReadAfter, sucess: true), 
			"D2" => AnalysisRead(analysis, data, AgreementaType.ReadAfter, sucess: false), 
			"94" => AnalysisRead(analysis, data, AgreementaType.Write, sucess: true), 
			"D4" => AnalysisRead(analysis, data, AgreementaType.Write, sucess: false), 
			"93" => AnalysisRead(analysis, data, AgreementaType.ReadAddress, sucess: true), 
			"95" => AnalysisRead(analysis, data, AgreementaType.WriteAddress, sucess: true), 
			"96" => AnalysisRead(analysis, data, AgreementaType.Frozen, sucess: true), 
			"D6" => AnalysisRead(analysis, data, AgreementaType.Frozen, sucess: false), 
			"97" => AnalysisRead(analysis, data, AgreementaType.CommunicationRate, sucess: true), 
			"D7" => AnalysisRead(analysis, data, AgreementaType.CommunicationRate, sucess: false), 
			"98" => AnalysisRead(analysis, data, AgreementaType.UpdatePwd, sucess: true), 
			"D8" => AnalysisRead(analysis, data, AgreementaType.UpdatePwd, sucess: false), 
			"99" => AnalysisRead(analysis, data, AgreementaType.MaxClear, sucess: true), 
			"D9" => AnalysisRead(analysis, data, AgreementaType.MaxClear, sucess: false), 
			"9A" => AnalysisRead(analysis, data, AgreementaType.Clear, sucess: true), 
			"DA" => AnalysisRead(analysis, data, AgreementaType.Clear, sucess: false), 
			"9B" => AnalysisRead(analysis, data, AgreementaType.EventClear, sucess: true), 
			"DB" => AnalysisRead(analysis, data, AgreementaType.EventClear, sucess: false), 
			"9C" => AnalysisRead(analysis, data, AgreementaType.SwitchOff, sucess: true), 
			"DC" => AnalysisRead(analysis, data, AgreementaType.SwitchOff, sucess: false), 
			"83" => AnalysisRead(analysis, data, AgreementaType.SafetyCertification, sucess: true), 
			"C3" => AnalysisRead(analysis, data, AgreementaType.SafetyCertification, sucess: false), 
			_ => false, 
		};
		if (1 == 0)
		{
		}
		bool suncess = flag;
		return analysis;
	}

	/// <summary>
	/// 读数据无后续数据
	/// </summary>
	/// <param name="analysis"></param>
	/// <param name="data"></param>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private static bool AnalysisRead(AgreementAnalysis analysis, Span<byte> data, AgreementaType type, bool sucess)
	{
		int length = data[9];
		Span<byte> info = data.Slice(10, length);
		string datainfo = "";
		Span<byte> span = info;
		for (int i = 0; i < span.Length; i++)
		{
			byte item = span[i];
			datainfo += item.ToString("x2");
		}
		analysis.Data = datainfo;
		analysis.Sucess = sucess;
		analysis.Type = type;
		return true;
	}

	public DL645Agreement()
	{
	}

	/// <summary>
	///
	/// </summary>
	/// <param name="passwd">等级+密码</param>
	/// <param name="operatorcode">操作者代码</param>
	public DL645Agreement(string passwd, string operatorcode)
	{
		_passwd = passwd;
		_operatorcode = operatorcode;
	}

	/// <summary>
	/// 获取发送数据格式
	/// </summary>
	/// <param name="agreementaType"></param>
	/// <param name="address"></param>
	/// <param name="data"></param>
	/// <param name="value">配合值设置使用</param>
	/// <returns></returns>
	/// <exception cref="T:System.ArgumentOutOfRangeException"></exception>
	public Span<byte> Send645Agreement(AgreementaType agreementaType, string address, string data = null, string value = null)
	{
		if (1 == 0)
		{
		}
		Span<byte> result = agreementaType switch
		{
			AgreementaType.Timing => AgreementTiming(address), 
			AgreementaType.Reading => AgreementReading(address, data), 
			AgreementaType.EventClear => AgreementEventClear(address), 
			AgreementaType.Clear => AgreementClear(address), 
			AgreementaType.ReadAfter => AgreementReadAfter(address, data), 
			AgreementaType.WriteAddress => AgreementWriteAddress(address), 
			AgreementaType.CommunicationRate => AgreementCommunicationRate(address, data), 
			AgreementaType.Frozen => AgreementFrozen(address, data), 
			AgreementaType.Write => AgreementWrite(address, data, value), 
			AgreementaType.ReadAddress => AgreementReadAddress(address), 
			AgreementaType.MaxClear => AgreementMaxClear(address, data), 
			AgreementaType.UpdatePwd => AgreementUpdatePwd(address, data), 
			AgreementaType.SwitchOff => AgreementSwitchOff(address, data), 
			AgreementaType.SendData => AgreementOther(address, data), 
			_ => throw new ArgumentOutOfRangeException("agreementaType"), 
		};
		if (1 == 0)
		{
		}
		return result;
	}

	/// <summary>
	/// 自定义指令
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	/// <returns></returns>
	private Span<byte> AgreementOther(string address, string data)
	{
		return InitIntegration(address, data, "1C");
	}

	/// <summary>
	/// 拉闸合闸
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data">1是合闸 2拉闸</param>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementSwitchOff(string address, string data)
	{
		string info = "";
		info = ((!(data == "1")) ? "3434343933333333333333333533" : "3435343933333333333333333633");
		return InitIntegration(address, info, "1C");
	}

	/// <summary>
	/// 修改密码
	/// </summary>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementUpdatePwd(string address, string data)
	{
		string info = "33333433" + _passwd + data;
		return InitIntegration(address, info, "18");
	}

	/// <summary>
	/// 最大需量清0
	/// </summary>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementMaxClear(string address, string data)
	{
		string info = _passwd + data;
		return InitIntegration(address, info, "19");
	}

	/// <summary>
	/// 读通讯地址
	/// </summary>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementReadAddress(string address)
	{
		Span<byte> bytes = new Span<byte>(new byte[16]);
		GetInitFE(bytes);
		string send = "68 AA AA AA AA AA AA 68 13 00 DF 16";
		string[] info = send.Split(' ');
		for (int i = 0; i < info.Length; i++)
		{
			bytes[i + 4] = (byte)Convert.ToInt32(info[i], 16);
		}
		return bytes;
	}

	private int GetCSCode(Span<byte> byteFrame)
	{
		int s = 0;
		for (int k = 0; k < byteFrame.Length; k++)
		{
			s += (byteFrame[k] & 0xFF) % 256;
		}
		return s;
	}

	private byte GetSigned(int a)
	{
		if (a > 127)
		{
			return (byte)(a - 256);
		}
		return (byte)a;
	}

	/// <summary>
	/// 添加默认FE
	/// </summary>
	/// <param name="bytes"></param>
	/// <returns></returns>
	private Span<byte> GetInitFE(Span<byte> bytes)
	{
		for (int i = 0; i < 4; i++)
		{
			bytes[i] = (byte)Convert.ToInt32("FE", 16);
		}
		return bytes;
	}

	/// <summary>
	/// 写数据
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementWrite(string address, string data, string value)
	{
		if (string.IsNullOrEmpty(data))
		{
			throw new ArgumentNullException("data", "当前写数据参数不能为空");
		}
		string info = data + _passwd + _operatorcode + value;
		return InitIntegration(address, info, "14");
	}

	/// <summary>
	/// 冻结
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data">99999999瞬时冻结默认的，99DDhhmm按月冻结</param>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementFrozen(string address, string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			data = "96969696";
		}
		return InitIntegration(address, data, "16");
	}

	/// <summary>
	/// 更改通讯速率
	/// </summary>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementCommunicationRate(string address, string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			throw new ArgumentNullException("data", "当前更改通讯速率参数不能为空");
		}
		return InitIntegration(address, data, "17");
	}

	/// <summary>
	/// 初始化整合操作
	/// </summary>
	/// <returns></returns>
	private Span<byte> InitIntegration(string address, string data, string code)
	{
		Span<byte> bytes = new Span<byte>(new byte[16 + data.Length / 2]);
		GetInitFE(bytes);
		SetCodeAndAddress(bytes, address, (data.Length / 2).ToString("x2"), code, data);
		int index = bytes.Length - 2;
		bytes[index] = GetSigned(GetCSCode(bytes.Slice(4)));
		bytes[++index] = (byte)Convert.ToInt32("16", 16);
		return bytes;
	}

	/// <summary>
	/// 写通讯地址
	/// </summary>
	/// <param name="address">dizhi</param>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementWriteAddress(string address)
	{
		return InitIntegration("AAAAAAAAAAAA", address, "15");
	}

	/// <summary>
	/// 读后续数据 
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	/// <returns></returns>
	private Span<byte> AgreementReadAfter(string address, string data)
	{
		if (string.IsNullOrEmpty(data))
		{
			throw new ArgumentNullException("data", "当前都后续数据参数不能为空");
		}
		return InitIntegration(address, data + "38", "12");
	}

	/// <summary>
	/// 电表清零
	/// </summary>
	/// <param name="address"></param>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementClear(string address)
	{
		string info = _passwd + _operatorcode;
		return InitIntegration(address, info, "1A");
	}

	/// <summary>
	/// 事件清零（默认事件总清0）
	/// </summary>
	/// <param name="address"></param>
	/// <returns></returns>
	private Span<byte> AgreementEventClear(string address)
	{
		string info = _passwd + _operatorcode + "32323232";
		return InitIntegration(address, info, "1B");
	}

	/// <summary>
	/// 读取
	/// </summary>
	/// <param name="address"></param>
	/// <param name="data"></param>
	/// <returns></returns>
	private Span<byte> AgreementReading(string address, string data)
	{
		return InitIntegration(address, data, "11");
	}

	/// <summary>
	/// 设置编码和地址
	/// </summary>
	/// <returns></returns>
	private Span<byte> SetCodeAndAddress(Span<byte> bytes, string address, string length, int code)
	{
		string info = $"68{address}68{code}{length}";
		int index = 0;
		for (int i = 0; i < info.Length; i += 2)
		{
			bytes[4 + index] = (byte)Convert.ToInt32(info.Substring(i, 2), 16);
			index++;
		}
		return bytes;
	}

	/// <summary>
	/// 设置编码和地址
	/// </summary>
	/// <returns></returns>
	private Span<byte> SetCodeAndAddress(Span<byte> bytes, string address, string length, string code, string data)
	{
		string info = $"68{address}68{code}{length}{data}";
		int index = 0;
		for (int i = 0; i < info.Length; i += 2)
		{
			bytes[4 + index] = (byte)Convert.ToInt32(info.Substring(i, 2), 16);
			index++;
		}
		return bytes;
	}

	/// <summary>
	/// 广播校验时间
	/// </summary>
	/// <returns></returns>
	/// <exception cref="T:System.NotImplementedException"></exception>
	private Span<byte> AgreementTiming(string address)
	{
		return InitIntegration(address, DateTime.Now.ToString("yyyyMMddHHmm"), "08");
	}
}
